package xyj.sparrow.scheduler.controller;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import xyj.sparrow.scheduler.annotation.UserValid;
import xyj.sparrow.scheduler.common.Result;
import xyj.sparrow.scheduler.cron.Cron;
import xyj.sparrow.scheduler.cron.ops.CronOps;
import xyj.sparrow.scheduler.cron.thread.MonitorThread;
import xyj.sparrow.scheduler.entity.App;
import xyj.sparrow.scheduler.entity.Task;
import xyj.sparrow.scheduler.mapper.AppMapper;
import xyj.sparrow.scheduler.mapper.TaskMapper;
import xyj.sparrow.scheduler.server.connect.ConnectManager;
import xyj.sparrow.scheduler.service.IAppService;
import xyj.sparrow.scheduler.vo.AppVO;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author jim
 * @since 2021-06-05
 */
@RestController
@RequestMapping("/api/v1/app")
@Slf4j
@CrossOrigin
public class AppController {
    @Resource
    private IAppService iAppService;
    @Resource
    private TaskMapper taskMapper;
    @Resource
    private AppMapper appMapper;
    @Resource
    private MonitorThread monitorThread;
    @Resource
    private CronOps cronOps;
    @Resource
    private ConnectManager connectManager;

    @PostMapping("/list")
    @UserValid
    public Result<IPage<AppVO>> listApp(@RequestBody Page<App> iPage) {
        if (iPage == null) {
            iPage = new Page<>();
        }
        QueryWrapper<App> query = new QueryWrapper<>();
        if (!iPage.getRecords().isEmpty()) {
            App app = iPage.getRecords().get(0);
            if (!StrUtil.isBlank(app.getAppName())) {
                query.like("app_name", app.getAppName());
            }
        }
        IPage<App> page = iAppService.page(iPage, query);
        IPage<AppVO> voiPage = fillUpClient(page);
        return Result.success(voiPage);
    }

    /**
     * 填补客户端信息
     *
     * @param page
     * @author Jim
     * @since 2021/6/16 上午10:28
     **/

    private IPage<AppVO> fillUpClient(IPage<App> page) {
        IPage<AppVO> newPage = new Page<>();
        newPage = Convert.convert(newPage.getClass(), page);
        List<AppVO> appVOS = new ArrayList<>();
        for (App record : page.getRecords()) {
            AppVO appVO = Convert.convert(AppVO.class, record);
            List<String> clients = listClientByAppId(appVO.getAppId());
            appVO.setClients(clients);

            appVOS.add(appVO);
        }
        newPage.setRecords(appVOS);
        return newPage;
    }

    private List<String> listClientByAppId(String appId) {
        return connectManager.listConnectDesc(appId);

    }

    @GetMapping("/list")
    @UserValid
    public Result<List<App>> listApp() {
        List<App> list = iAppService.list();
        return Result.success(list);
    }

    @PostMapping("")
    @UserValid
    public Result<App> addApp(@RequestBody App app) {
        app.setCreateTime(LocalDateTime.now());
        app.setUpdateTime(LocalDateTime.now());
        iAppService.save(app);
        return Result.success(app);
    }

    @PutMapping("")
    @UserValid
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> updateApp(@RequestBody App app) {
        app.setUpdateTime(LocalDateTime.now());
        iAppService.updateById(app);
        if (app.getAppStatus() == 1) {
            List<Task> tasks = taskMapper.listTaskOfEnableByAppId(app.getAppId());
            tasks.forEach(task -> {
                Cron cron = new Cron(monitorThread, task);
                cronOps.updateCron(cron);
            });
        } else {
            cronOps.removeByAppIds(Collections.singletonList(app.getAppId()));
        }

        return Result.success();
    }

    @DeleteMapping("/{appId}")
    @UserValid
    public Result<Object> deleteApp(@PathVariable("appId") String appId) {
        iAppService.removeById(appId);
        cronOps.removeByAppIds(Collections.singletonList(appId));
        return Result.success();
    }

    @DeleteMapping("/")
    @UserValid
    public Result<Object> batchDeleteApp(@RequestBody List<String> ids) {
        iAppService.removeByIds(ids);
        cronOps.removeByAppIds(ids);
        return Result.success();
    }

    @PutMapping("/{ops}")
    @UserValid
    public Result<Object> batchOpsApp(@RequestBody List<String> ids, @PathVariable("ops") String ops) {
        UpdateWrapper<App> updateWrapper = new UpdateWrapper<>();
        if ("enabled".equals(ops)) {
            updateWrapper.set("app_status", 1);
            updateWrapper.in("app_id", ids);
            iAppService.update(updateWrapper);
            //批量更新
            cronOps.batchUpdateCronByAppId(ids);
        } else {
            //批量禁用app
            updateWrapper.set("app_status", 0);
            updateWrapper.in("app_id", ids);
            iAppService.update(updateWrapper);
            cronOps.removeByAppIds(ids);
        }

        return Result.success();
    }
}

